package com.bajie.bjlisten.sevice;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.bajie.bjlisten.dto.UserConstants;
import com.bajie.bjlisten.entity.*;
import com.bajie.bjlisten.entity.request.QueryUserRequest;
import com.bajie.bjlisten.entity.response.*;
import com.bajie.bjlisten.enums.DeviceTypeEnum;
import com.bajie.bjlisten.enums.UserStateEnum;
import com.bajie.bjlisten.exception.ExceptionCast;
import com.bajie.bjlisten.mapper.BjDeviceMessageMapper;
import com.bajie.bjlisten.mapper.BjUserMapper;
import com.bajie.bjlisten.mapper.BjUserRoleMapper;
import com.bajie.bjlisten.utils.StringUtils;
import com.bajie.bjlisten.utils.UserUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;


import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("bjUserService")

public class BjUserService {
    private static final Logger log = LoggerFactory.getLogger("adminLogger");
    @Autowired
    BjUserMapper bjUserMapper;

    @Autowired
    BjUserRoleMapper bjUserRoleMapper;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    BjAdsService bjAdsService;

    @Autowired
    BjInviteService bjInviteService;
    @Autowired
    BjDeviceMessageMapper bjDeviceMessageMapper;

    @Autowired
    BjSignService bjSignService;

    /**
     * 根据用户名和密码查询
     *
     * @param userName
     * @param password
     * @return
     */
    public BjUser findByUserNameAndUserPass(String userName, String password) {
        return bjUserMapper.findByUserNameAndUserPass(userName, password);
    }

    /**
     * 根据邮箱和密码查询
     *
     * @param userEmail
     * @param password
     * @return
     */
    public BjUser findByUserEmailAndUserPass(String userEmail, String password) {
        return bjUserMapper.findByUserEmailAndUserPass(userEmail, password);
    }

    /**
     * 根据用户Id和密码查询
     *
     * @param userId
     * @param password
     * @return
     */
    public BjUser findByUserIdAndUserPass(String userId, String password) {
        return bjUserMapper.findByUserIdAndUserPass(userId, password);
    }

    /**
     * 根据手机号码查询
     *
     * @param phone
     * @return
     */
    public BjUser findByUserMobile(Long phone) {
        return bjUserMapper.findByUserMobile(phone);
    }

    /**
     * 根据用户ID查询
     *
     * @return
     */
    public BjUser findByUserId(String userId) {
        return bjUserMapper.findByUserId(userId);
    }

    /**
     * 根据注册的开始时间段内查询
     *
     * @param beginRegister
     * @param endRegister
     * @return
     */
    public BjUserListResult findByRegisterTime(String beginRegister, String endRegister) {
        List<BjUser> list = bjUserMapper.findByRegisterTime(beginRegister, endRegister);
        return new BjUserListResult(CommonCode.SUCCESS, list);
    }

    /**
     * 查询所有用户
     *
     * @return
     */
    public BjUserListResult findAll() {
        List<BjUser> list = bjUserMapper.findAll();
        return new BjUserListResult(CommonCode.SUCCESS, list);
    }


    /**
     * 根据用户名查询
     */
    public BjUser findByUserName(String userName) {
        return bjUserMapper.findByUserName(userName);

    }

    /**
     * 根据查询条件查询用户列表信息
     * @param queryCond
     * @return
     */
    public List<BjUser> findByCond(QueryUserRequest queryCond) {
        return bjUserMapper.getUsersByCond(queryCond);

    }

    /**
     * 保存用户
     *
     * @param bjUser
     * @return 不用这个方法
     */
    @CachePut(value="bjUser", key="#bjUser.id")
    @Transactional
    public int saveUserData(BjUser bjUser) {

        return bjUserMapper.saveData(bjUser);
    }

    /*----------------------用下面的代码-----------------------------------------*/

    public List<BjUser> list(Map<String, Object> params, Integer offset,
                             Integer limit) {
        return bjUserMapper.list(params, offset, limit);

    }

    public Integer count(Map<String, Object> params) {
        return bjUserMapper.count(params);
    }


    public String passwordEncoder(String credentials, String salt) {
        Object object = new SimpleHash("MD5", credentials, salt, UserConstants.HASH_ITERATIONS);
        return object.toString();
    }

    /**
     * 新增用户
     *
     * @param userDto
     * @return
     */
    @Transactional
    public BjUser saveUser(BjuserDto userDto) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS");
        Date time = null;
        try {
            time = sdf.parse(sdf.format(new Date()));

        } catch (ParseException e) {

            e.printStackTrace();
        }
        BjuserDto user = userDto;
        user.setSalt(DigestUtils
                .md5Hex(UUID.randomUUID().toString() + System.currentTimeMillis() + UUID.randomUUID().toString()));
        user.setPassword(passwordEncoder(user.getPassword(), user.getSalt()));

        user.setEnablestate(UserStateEnum.ON);
        user.setCreate_time(time);
        bjUserMapper.saveData(user);
        saveUserRoles(user.getId(), userDto.getRoleIds());

        log.debug("新增用户{}", user.getUsername());
        return user;
    }

    /**
     * 根据用户ID和角色的集合保存
     *
     * @param userId
     * @param roleIds
     */

    @Transactional
    public void saveUserRoles(String userId, List<String> roleIds) {
        if (roleIds != null) {
            bjUserRoleMapper.deleteUserRole(userId);
            if (StringUtils.isNotEmpty(roleIds)) {
                bjUserRoleMapper.saveUserRoles(userId, roleIds);
            }
        }
    }

    /**
     * 根据用户名 新密码和旧密码修改密码
     *
     * @param username
     * @param oldPassword
     * @param newPassword
     */
    @Transactional
    public void changePassword(String username, String oldPassword, String newPassword) {
        BjUser u = bjUserMapper.findByUserName(username);
        if (u == null) {
            throw new IllegalArgumentException("用户不存在");
        }
        if (!StringUtils.isEqual(u.getPassword(), passwordEncoder(oldPassword, u.getSalt()))) {
            throw new IllegalArgumentException("密码错误");
        }
        bjUserMapper.changePassword(u.getId(), passwordEncoder(newPassword, u.getSalt()));

        log.debug("修改{}的密码", username);
    }

    /**
     * 更新用户信息
     *
     * @param userDto
     * @return
     */
    @Transactional
    public BjUser updateUser(BjuserDto userDto) {
        bjUserMapper.updateByUserId(userDto);
        saveUserRoles(userDto.getId(), userDto.getRoleIds());
        updateUserSession(userDto.getId());

        return userDto;
    }

    //更新用户的Session
    @Transactional

    public void updateUserSession(String id) {
        BjUser current = UserUtil.getCurrentUser();
        if (current.getId().equals(id)) {
            BjUser user = bjUserMapper.findByUserId(id);
            UserUtil.setUserSession(user);
        }
    }

    @Transactional
    public int insertUserByImei(String imei, String age,  String sex) {

        int value = bjUserMapper.insertUserByImei(imei,age,sex);
        if (value > 0)
            return value;
        else
            throw new RuntimeException();
    }

    @Transactional
    public int insertUserByUnique(String appunique, String age,  String sex) {
        int value = bjUserMapper.insertUserByUnique(appunique,age,sex);
        if (value > 0)
            return value;
        else
            throw new RuntimeException();

    }


    public BjUser getUserByEmei(String imei) {
        return bjUserMapper.getUserByEmei(imei);
    }

    public BjUser getUserByUnique(String appunique) {
        return bjUserMapper.getUserByUnique(appunique);
    }

    @Transactional
    public int updateByImei(Map<String, String> params) {
        int value = bjUserMapper.updateByImei(params);
        if (value > 0)
            return value;
        else
            throw new RuntimeException();
    }

    @Transactional
    public int updateByAppunique(Map<String, String> params) {
        int value = bjUserMapper.updateByAppunique(params);
        if (value > 0)
            return value;
        else
            throw new RuntimeException();

    }

    /**
     * 插入带入的emei/邀请码/唯一值，然后返回用户信息
     * @param mapvalue
     * @return
     */
    public BjUserResult getBjUserByImei( Map<String, String> mapvalue){
        {

            String imei = mapvalue.get("imei");//邀请码就是userId
            String invitationCode = mapvalue.get("invitationCode");
            String uniqueCode = mapvalue.get("appunique");

            String sex=mapvalue.get("sex");
            String age=mapvalue.get("age");

            BjUser countUser = null;
            int returnUserValue = 0;//根据imei插入用户表
            int returnInviteValue = 0;//根据邀请码invitationCode插入邀请表返回值

            boolean imeiOrAppunique = false;//标识符，用于imei和appunique的标识符;true表示imei已经被app传参到后端
            boolean trueimei = false;//当imei已经不存在于用户表中
            String imei_unique = null;


            if (StringUtils.isNotEmpty(imei)) {  //imei不为空
                imeiOrAppunique = true;
                countUser = getUserByEmei(imei);
                if (null == countUser || StringUtils.isEmpty(countUser.getImei())) {//imei不存在于用户表里
                    returnUserValue = insertUserByImei(imei,age,sex);
                    imei_unique = imei;

                } else {
                    trueimei = true;

                    //更新邀请表
                    return new BjUserResult(CommonCode.SUCCESS, countUser);
                }
            } else {
                if (StringUtils.isNotEmpty(uniqueCode)) {
                    countUser = getUserByUnique(uniqueCode);
                    if (null == countUser || StringUtils.isEmpty(countUser.getAppunique())) {//当根据appunique查询不出值
                        returnUserValue = insertUserByUnique(uniqueCode,age,sex);
                        imei_unique = uniqueCode;
                    } else {
                        countUser = getUserByUnique(uniqueCode);
                        return new BjUserResult(CommonCode.SUCCESS, countUser);

                    }


                }
                //当app获取不到imei时，app会生成唯一值uniqueCode，返回给后端
            }

            if (returnUserValue != 0) { //当根据imei/appunique的信息插入用户表成功


                if (StringUtils.isNotEmpty(invitationCode)) { //邀请码不为空

                    //根据imei查询出的用户Id=邀请表的邀请人=邀请表的邀请码、APP传参的邀请码=邀请表的上级邀请人
                    //TODO 当根据imei查询用户信息表的用户ID存在于邀请表的的userId
                    //TODO 当imei已经存在于用户表，那么用户表不需要插入，说明邀请表也已经存在邀请表的邀请人Id和邀请码，
                    //      直接更新(当用户ID=现在app传参的邀请码)被邀请人=现在生成的用户的用户ID即可
                    // TODO  针对被邀请人，邀请人是被邀请人的上级邀请人
                    //TODO
                    BjInvite bjInvite = new BjInvite();
                    if (imeiOrAppunique) {
                        countUser = getUserByEmei(imei);
                        bjInvite.setUserId(countUser.getId());
                        bjInvite.setParentId(invitationCode);
                        bjInvite.setInvitationCode(countUser.getId());


                    } else {
                        countUser = getUserByUnique(uniqueCode);
                        bjInvite.setUserId(countUser.getId());
                        bjInvite.setParentId(invitationCode);
                        bjInvite.setInvitationCode(countUser.getId());
                    }
                    returnInviteValue =bjInviteService.saveBjInvite(bjInvite);


                } else {
                    if (imeiOrAppunique)
                        countUser = getUserByEmei(imei);
                    else
                        countUser = getUserByUnique(uniqueCode);

                }
                if (StringUtils.isNotEmpty(imei_unique)) {
                    BjAds bjAds = new BjAds();
                    bjAds.setImei_unique(imei_unique);
                    bjAds.setUserId(countUser.getId());
                    bjAds.setAdSources(mapvalue.get("adSources"));
                    bjAdsService.save(bjAds);
                }


                return new BjUserResult(CommonCode.SUCCESS, countUser);
            }
            if (returnInviteValue != 0) {//邀请表插入成功
                return new BjUserResult(CommonCode.SUCCESS, countUser);
            }

            ////邀请表插入不成功


            //当用户表插入不成功，后面就不需要执行了；
            //当imei和邀请码都存在的情况下，当用户表插入成功，邀请表插入不成功，这个也算报错；
            //当imei存在和邀请码为空的情况下，当用户表插入成功，邀请表插入成功，算成功


            return new BjUserResult(BjUserCode.BJUSER_GET_FAIL);


        }

    }

    /**
     *第二次传入imei/或者唯一值
     * 根据imei更新用户信息[授权传参给后端]
     * @param mapvalue
     * @return
     */
    public BjUserResult updateByTelImei(Map<String, String> mapvalue){
        {
            String imei = mapvalue.get("imei");//
            String appunique = mapvalue.get("appunique");
            String openId = mapvalue.get("openid");
            int device_type=Integer.parseInt(mapvalue.get("device_type"));



            int updateCount = 0;
            boolean isImei = false;

            if (StringUtils.isEmpty(openId)) {
                return new BjUserResult(BjUserCode.BJUSER_GET_FAIL);
            }

            if (StringUtils.isNotEmpty(imei)) {
                isImei = true;
                BjUser countUser = getUserByEmei(imei);
                if (null != countUser && StringUtils.isNotEmpty(countUser.getImei())) { //前端传入的是存在于用户表里

                    updateCount = updateByImei(mapvalue);//更新表
                }

            } else if (StringUtils.isNotEmpty(appunique)) {
                BjUser countUser = getUserByUnique(appunique);
                if (null != countUser && StringUtils.isNotEmpty(countUser.getId())) {

                    updateCount = updateByAppunique(mapvalue);
                }

            }

            BjUser user = null;

            if (updateCount != 0 && isImei)
                //更新的成功的话，再来查询
                user = getUserByEmei(imei);


            else if (updateCount != 0 && !isImei)
                user = getUserByUnique(appunique);


            BjDeviceMessage bjDeviceMessage=new BjDeviceMessage();
            if (null != user && StringUtils.isNotEmpty(user.getId())){
                bjDeviceMessage.setUserId(user.getId());
                bjDeviceMessage.setDevice_type(device_type==1?DeviceTypeEnum.ANDROID:DeviceTypeEnum.IOS);
                bjDeviceMessage.setDevice_token(imei);
                bjDeviceMessageMapper.save(bjDeviceMessage);//保存到设备消息表中
                return new BjUserResult(CommonCode.SUCCESS, user);
            }

            return new BjUserResult(BjUserCode.BJUSER_GET_FAIL);
        }

    }


    //app 传输userId和手机号码
    public ResponseResult getTelCode(String phoneNumber,String userId) {
        //根据用户Id查询用户信息
        BjUser bjUser= bjUserMapper.findByUserId(userId);
        int value=0;
        if((null==bjUser.getPhone()||0==bjUser.getPhone())&&StringUtils.isNotEmpty(phoneNumber)){
            bjUser.setPhone(Long.parseLong(phoneNumber));
            value=bjUserMapper.updateByUserId(bjUser);//更新用户信息手机号码==用户ID和手机号码绑定在一起
        }
        //当手机号码更新到用户表或者根据用户ID查询出的手机号码跟APP传参的手机号码一致
        if(value>0||(0!=bjUser.getPhone()&&StringUtils.isEqual(bjUser.getPhone().toString(),phoneNumber))){
            getCode(phoneNumber);
            return new ResponseResult(CommonCode.SUCCESS);
        }

            return new ResponseResult(CommonCode.FAIL);





    }

    /**
     * 获取手机验证码
     * @param phoneNumber
     * @return
     */

    public ResponseResult getCode(String phoneNumber) {

        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        //随机生成六位验证码
        int sixcode = (int) ((Math.random() * 9 + 1) * 100000);
        String code = JSON.toJSONString(sixcode);


        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAIxsRJNYwixqYe", "dtzvRp4pbT4C7oliTS6779l6ArfaUW");

        //DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        //request.setProtocol(ProtocolType.HTTPS);
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");

        SendSmsRequest smsRequest = new SendSmsRequest();

        smsRequest.setPhoneNumbers(phoneNumber);

        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", smsRequest.getPhoneNumbers());
        request.putQueryParameter("SignName", "八戒听书");
        request.putQueryParameter("TemplateCode", "SMS_162221042");
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }

        saveCaptcha( phoneNumber, code,  300);
        return new ResponseResult(CommonCode.SUCCESS);
    }
    private boolean saveCaptcha(String phone,String code, long ttl) {

        stringRedisTemplate.boundValueOps(phone).set(code, ttl, TimeUnit.SECONDS);
        Long expire = stringRedisTemplate.getExpire(phone, TimeUnit.SECONDS);
        return expire > 0;
    }

    public ResponseResult loginByPhone(String userId,String phoneNumber,String yzCode){
        //先判断userId是否存在用户手机号码
        BjUser bjUser=bjUserMapper.findByUserId(userId);
        if(null==bjUser||StringUtils.isEmpty(phoneNumber)||Long.parseLong(phoneNumber)!=bjUser.getPhone()){//传输的手机号码和userId对应的手机号码不一致

            ExceptionCast.cast(CommonCode.PHONENUMBER_ISNULL);


        }
        else {
           String captcha=stringRedisTemplate.opsForValue().get(phoneNumber);
           log.debug("从redis获取到的验证码为222"+captcha);
           System.out.println("从redis获取到的验证码为"+captcha);
           if(null!=phoneNumber&&StringUtils.isEqual(yzCode,captcha)){//比较验证码
               return new ResponseResult(CommonCode.SUCCESS);
           }

        }
        return new ResponseResult(CommonCode.FAIL);

    }

    /**
     * 根据用户查询被邀请的人
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
   public BjUserResult findAllByUserIds(String userId, Integer offset,Integer limit) {
        List<String> userIdslist=new ArrayList<>();//存放用户ID集合
        List<BjInvite> bjInviteList=bjInviteService.findByParentId(userId, offset, limit);
        if (StringUtils.isNotEmpty(bjInviteList)){
            for (int i = 0; i < bjInviteList.size(); i++) {
                userIdslist.add(bjInviteList.get(i).getUserId());
            }

        }
        List<BjUser> userList=bjUserMapper.findAllByUserIds(userIdslist,offset,limit);
        if (StringUtils.isNotEmpty(userList)){
            return new BjUserResult(CommonCode.SUCCESS,userList);
        }
       return new BjUserResult(BjUserCode.BJUSER_GET_FAIL);

    }

    //今日收入=邀请获取的金币+签到得到的金币
    public JSONObject findSumCoinByUserId(String userId){
        JSONObject json=new JSONObject();
        Map<String, BigDecimal> mapInviteToday=bjInviteService.findByParentIdAndToday(userId);
        Map<String, BigDecimal> mapInviteYesday=bjInviteService.findByParentIdAndYesterday(userId);
        BigDecimal sumcoinToday = BigDecimal.valueOf(0);//今天的邀请获得的金币总和
        BigDecimal sumcoinYesday = BigDecimal.valueOf(0);//昨天的邀请获得的金币总和
        if (StringUtils.isNotEmpty(mapInviteToday)){
            sumcoinToday=mapInviteToday.get("sumcoin");

        }
        if(StringUtils.isNotEmpty(mapInviteYesday)){
            sumcoinYesday=mapInviteYesday.get("sumcoin");
        }
        BjSign bjSignToday=bjSignService.findSignToday(userId);//今天的签到获得金币综合
        BjSign bjSignYesday=bjSignService.findSignYestoday(userId);//昨天的签到获得金币综合
        Integer signCoinToday = new Integer(0);//今天签到
        Integer signCoinYesday = new Integer(0);//昨天签到
        if (null !=bjSignToday){
            signCoinToday=bjSignToday.getVirtual_coin();
        }
        if (null !=bjSignYesday){
            signCoinYesday=bjSignYesday.getVirtual_coin();
        }
        BigDecimal signCoinAllToday = new BigDecimal(signCoinToday.toString());
        BigDecimal signCoinAllYesday = new BigDecimal(signCoinYesday.toString());
        json.put("userId",userId);
        json.put("sumcoinToday",sumcoinToday.add(signCoinAllToday));
        json.put("sumcoinYesterday",sumcoinYesday.add(signCoinAllYesday));

        Map<String, BigDecimal> sumcoinAll= bjInviteService.findAllByParentId(userId);//历史总收入
        Map<String, BigDecimal> signcoinAll=bjSignService.findSumCoinByUserId(userId);//用户所有的的签到获得金币综合

        BigDecimal sumcoinTotal = BigDecimal.valueOf(0);
        if(StringUtils.isNotEmpty(sumcoinAll)){
            sumcoinTotal=sumcoinAll.get("sumcoin");
        }
        BigDecimal sumSignTotal = BigDecimal.valueOf(0);
        if(StringUtils.isNotEmpty(signcoinAll)){
            sumSignTotal=signcoinAll.get("sumcoin");
        }

        json.put("sumcoinAll",sumcoinTotal.add(sumSignTotal));
        return  json;
    }

    //邀请获取的金币 根据邀请的时间和上级邀请人查询邀请表的金币
    //签到得到的金币 根据用户和时间查询今天得到的金币

    //获取用户总金额 历史总收入-提现的金额之和





}
